/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package edu.chl.vrangogym.beans.backing;

import edu.chl.vrangogym.persistence.entities.Booking;
import edu.chl.vrangogym.persistence.entities.User;
import edu.chl.vrangogym.persistence.entities.WorkoutSession;
import edu.chl.vrangogym.persistence.impl.BookingFacade;
import edu.chl.vrangogym.persistence.impl.UserFacade;
import edu.chl.vrangogym.persistence.impl.WorkoutSessionFacade;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.validation.constraints.NotNull;
import org.primefaces.event.DateSelectEvent;
import org.primefaces.event.FlowEvent;

/**
 *
 * @author habbbe
 */
@ManagedBean(name = "BookingBackingBean")
@ViewScoped
public class BookingBackingBean {

    @EJB
    private BookingFacade bookingFacade;
    @EJB
    private WorkoutSessionFacade workoutSessionFacade;
    
    @EJB
    private UserFacade userFacade;
    
    
    /*********Schedule config*********/
    private final int maxParticipants = 3;
    
    private final int bookingRange = 14;
    
    private final int sessionLength = 1;
    
    private final int openingHour = 8;
    
    private final int closingHour = 22;
    
    private final int maxGroupParticipants = 8;
    
    /*********************************/
    
    @NotNull
    private Date date;
    
    private String currentDate;
    private String maxDate;
    
    private WorkoutSession selectedWorkoutSession;
    private int selectedNumberOfParticipant;
    
    private String bookingComment;

    public String getBookingComment() {
        return bookingComment;
    }

    public void setBookingComment(String bookingComment) {
        this.bookingComment = bookingComment;
    }

    public int getSelectedNumberOfParticipant() {
        return selectedNumberOfParticipant;
    }

    public void setSelectedNumberOfParticipant(int selectedNumberOfParticipant) {
        this.selectedNumberOfParticipant = selectedNumberOfParticipant;
    }

    public WorkoutSession getSelectedWorkoutSession() {
        return selectedWorkoutSession;
    }

    public void setSelectedWorkoutSession(WorkoutSession selectedWorkoutSession) {
        this.selectedWorkoutSession = selectedWorkoutSession;
    }

    /** Creates a new instance of WorkoutSessionProviderBean */
    public BookingBackingBean() {
    }

   

    /**
     *
     * Fetch workout sessions that reached its limit in participants.
     * 
     * @return the workout sessions that reached its limit in participants.
     */
    private List<WorkoutSession> getUnavailableWorkoutSessions() {

        List<WorkoutSession> unavailableSessions = new ArrayList<WorkoutSession>();

        User user = (User)FacesContext.getCurrentInstance().getExternalContext()
                    .getSessionMap().get("Auth.user");
        
        boolean dontAdd = false;
        
        /*
         * Fetch workout sessions that reached its limit in participants (3).
         */
        int totalParticipants;
        for (WorkoutSession ws : workoutSessionFacade.findAll()) {
            dontAdd = false;
            totalParticipants = 0;
            for (Booking b : bookingFacade.getBookingsForWorkoutSession(ws)) {
                totalParticipants += b.getParticipants();
                if (b.getBooker().equals(user)) {
                    dontAdd = true;
                    unavailableSessions.add(ws);
                }
            }
            if (!dontAdd && totalParticipants >= maxParticipants) {
                unavailableSessions.add(ws);
            }
        }
        return unavailableSessions;
    }

    /**
     * 
     * Returns current date in format compatible with maxdate and mindate in
     * Primefaces calendar. MM/DD/YYYY
     * @return the formatted current date
     */
    public String getCurrentDate() {
        return getFormattedDate(new Date());
    }

    /**
     * Formats date to a string with US standard
     * @param date
     * @return 
     */
    private String getFormattedDate(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
        return format.format(date);
    }
    
    /**
     * Get available workout sessions for selected day
     * @return 
     */
    public List<WorkoutSession> getAvailableWorkoutSessions() {
        
        List<WorkoutSession> resultList = new ArrayList<WorkoutSession>();
        
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        
        
        
        cal.set(Calendar.HOUR_OF_DAY, openingHour); 
        
        for (int i = openingHour; i < closingHour; i += sessionLength) {
            Date startTime = cal.getTime();
            cal.add(Calendar.HOUR_OF_DAY, sessionLength);
            Date endTime = cal.getTime();
            WorkoutSession ws = new WorkoutSession(startTime, endTime);
            resultList.add(ws);
        }
        
        resultList.removeAll(getUnavailableWorkoutSessions());
        
        return resultList;
        
    }

    /**
     * Listener for selection on Primefaces calendar
     * @param evt 
     */
    public void dateSelectedListener(DateSelectEvent evt) {
        System.out.println(getFormattedDate(evt.getDate()));
    }

    /**
     * Return the date of the last bookable date in format compatible with maxdate and mindate in
     * Primefaces calendar. MM/DD/YYYY
     * @return the formatted date of the last bookable date
     */
    public String getMaxDate() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_MONTH, bookingRange);
        return getFormattedDate(cal.getTime());
    }
    
    /**
     * Returns the maximum specified participants in group booking
     * @return 
     */
    public List<Integer> getMaxGroupParticipants() {
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 1; i <= maxGroupParticipants; i++) {
            list.add(i);
        }
        return list;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public Date getDate() {
        return date;
    }

    public String onFlowProcess(FlowEvent event) {
        return event.getNewStep();
    }
}
